package com.xmtlxx.web.controller.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.xmtlxx.web.controller.center.service.ICommonService;
import com.xmtlxx.web.controller.oms.service.ITaskService;
import com.xmtlxx.web.controller.wms.service.IDealService;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.domain.entity.SysDept;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.exception.ServiceException;
import com.xmtlxx.common.helper.LoginHelper;
import com.xmtlxx.common.utils.DateUtils;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.oms.domain.OperatorLog;
import com.xmtlxx.oms.domain.TaskDtl;
import com.xmtlxx.oms.domain.vo.PropertyVo;
import com.xmtlxx.oms.domain.vo.TaskDtlVo;
import com.xmtlxx.oms.domain.vo.TaskVo;
import com.xmtlxx.oms.mapper.OperatorLogMapper;
import com.xmtlxx.oms.mapper.PropertyMapper;
import com.xmtlxx.oms.mapper.TaskDtlMapper;
import com.xmtlxx.oms.mapper.TaskMapper;
import com.xmtlxx.system.domain.SysOss;
import com.xmtlxx.system.domain.bo.SysOssBo;
import com.xmtlxx.system.mapper.SysDeptMapper;
import com.xmtlxx.system.mapper.SysOssMapper;
import com.xmtlxx.tms.domain.OrderDtl;
import com.xmtlxx.tms.domain.bo.OrderBo;
import com.xmtlxx.tms.domain.vo.OrderVo;
import com.xmtlxx.tms.mapper.OrderDtlMapper;
import com.xmtlxx.tms.mapper.OrderMapper;
import com.xmtlxx.wms.domain.Deal;
import com.xmtlxx.wms.domain.DealDtl;
import com.xmtlxx.wms.domain.Inventory;
import com.xmtlxx.wms.domain.bo.DealBo;
import com.xmtlxx.wms.domain.vo.DealDtlVo;
import com.xmtlxx.wms.domain.vo.DealVo;
import com.xmtlxx.wms.mapper.DealDtlMapper;
import com.xmtlxx.wms.mapper.DealMapper;
import com.xmtlxx.wms.mapper.InventoryMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 处置Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DealServiceImpl implements IDealService {

    private final DealMapper baseMapper;

    private final DealDtlMapper dealDtlMapper;

    private final SysOssMapper sysOssMapper;

    private final OrderMapper orderMapper;

    private final OrderDtlMapper orderDtlMapper;

    private final TaskMapper taskMapper;

    private final TaskDtlMapper taskDtlMapper;

    private final OperatorLogMapper logMapper;

    private final InventoryMapper inventoryMapper;

    private final ICommonService commonService;

    private final SysDeptMapper deptMapper;

    private final ITaskService taskService;

    private final PropertyMapper propertyMapper;

    /**
     * 查询处置
     *
     * @param id 处置主键
     * @return 处置
     */
    @Override
    public DealVo queryById(String id){
        //return baseMapper.selectVoById(id);
        return baseMapper.selectDealVoByID(id);
    }

    @Override
    public DealVo queryByTaskId(String taskId) {
        return baseMapper.selectDealVoByTaskId(taskId);
    }

    @Override
    public TaskVo initDealBean(List<String> ids) {
        TaskVo bo = new TaskVo();
        bo.setType("2");
        TaskVo vo =  taskService.initBean(bo);

        if(ids != null && ids.size() > 0){
            List<TaskDtlVo> dtls = ids.stream().map(id->{
                DealVo deal = baseMapper.selectDealVoByID(id);
                TaskDtlVo dtl = new TaskDtlVo();
                PropertyVo property = propertyMapper.selectPropertyVoByPno(deal.getDealNo());
                BeanUtil.copyProperties(property,dtl);
                dtl.setNums(deal.getNums());
                dtl.setDealType(deal.getDealType());

                SysOssBo ossBo = new SysOssBo();
                ossBo.setBuss("property");
                ossBo.setObjid(property.getPno());
                dtl.setOss(sysOssMapper.selectSysOssList(ossBo));
                deal.setTaskId(vo.getId());
                return dtl;
            }).collect(Collectors.toList());
            vo.setDealType(dtls.get(0).getDealType());
            vo.setItems(dtls);
            vo.setDealIds(ids);
        }
        return vo;
    }

    /**
     * 查询处置列表
     *
     * @param bo 处置
     * @return 处置
     */
    @Override
    public TableDataInfo<DealVo> queryPageList(DealBo bo, PageQuery pageQuery) {
       // LambdaQueryWrapper<Deal> lqw = buildQueryWrapper(bo);
       // Page<DealVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        SysDept dept = deptMapper.selectById(LoginHelper.getDeptId());
        if(dept != null && StringUtils.isNotBlank(dept.getDeptCode())){
            if (dept.getDeptCode().startsWith("3504") && !dept.getDeptCode().equals("0") && !dept.getDeptCode().equals("001") && !dept.getDeptCode().equals("002")){
                bo.setProOfficeId(dept.getDeptId());
            }
        }
        Page<DealVo> result = baseMapper.selectPageDealList(pageQuery.build(), bo);
        if(result != null && result.getRecords() != null && result.getRecords().size() > 0){
            for (DealVo vo :result.getRecords()){
                //处理pdf附件
                if(StringUtils.isNotEmpty(vo.getWsPdf())){
                    List<String> pdfList = new ArrayList<>();
                    if(vo.getWsPdf().startsWith("[")){
                        JSONArray wsPdfDatas = JSONArray.parseArray(vo.getWsPdf());
                        wsPdfDatas.removeAll(Collections.singleton(null));
                        for (int i = 0;i<wsPdfDatas.size();i++){
                            pdfList.add(wsPdfDatas.get(i).toString());
                        }
                    }else{
                        pdfList.add(vo.getWsPdf());
                    }
                    vo.setPdfList(pdfList);
                }
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询处置列表
     *
     * @param bo 处置
     * @return 处置
     */
    @Override
    public List<DealVo> queryList(DealBo bo) {
       // LambdaQueryWrapper<Deal> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectDealList(bo);
    }

    private LambdaQueryWrapper<Deal> buildQueryWrapper(DealBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Deal> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTaskId()), Deal::getTaskId, bo.getTaskId());
        lqw.eq(StringUtils.isNotBlank(bo.getDealNo()), Deal::getDealNo, bo.getDealNo());
        lqw.eq(bo.getDeptId() != null, Deal::getDeptId, bo.getDeptId());
        lqw.eq(bo.getOperator() != null, Deal::getOperator, bo.getOperator());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Deal::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getHandId()), Deal::getHandId, bo.getHandId());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            Deal::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), Deal::getCreateBy, bo.getCreateBy());
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), Deal::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增处置
     *
     * @param bo 处置
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Deal insertByBo(DealBo bo) {
        Deal add = BeanUtil.toBean(bo, Deal.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");
        add.setStatus("0");
//        add.setDealNo(getNo());

        List<DealDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            for (DealDtlVo item : bo.getItems()){
                DealDtl dtl = BeanUtil.toBean(item, DealDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setDealId(add.getId());
                dtl.setDelFlag("0");
                dtl.setNums(item.getNums() == null ? 1L : item.getNums());

                if(!LoginHelper.checkLoginUser()){
                    dtl.setCreateBy("admin");
                    dtl.setCreateTime(new Date());
                    dtl.setUpdateBy("admin");
                    dtl.setUpdateTime(new Date());
                }

                dtls.add(dtl);
            }
        }
        if(!LoginHelper.checkLoginUser()){
            add.setCreateBy("admin");
            add.setCreateTime(new Date());
            add.setUpdateBy("admin");
            add.setUpdateTime(new Date());
        }
        boolean flag = baseMapper.insert(add) > 0;
        if(dtls != null && dtls.size() > 0){
            dealDtlMapper.insertBatch(dtls);
        }
        if (flag) {
            bo.setId(add.getId());
        }
        if(bo.getOss() != null && bo.getOss().size() > 0){
            for(SysOss oss : bo.getOss()){
                oss.setBuss("Deal");
                oss.setObjid(add.getId());
                sysOssMapper.updateById(oss);
            }
        }
        addOperatorLog(StringUtils.isNotEmpty(add.getTaskId())?add.getTaskId():add.getId(),"wms","创建处置单");
        return add;
    }

    @Override
    public Deal insertByDealBo(DealBo bo) {
        Deal add = BeanUtil.toBean(bo, Deal.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");
        add.setStatus("0");
        add.setIsFinish("0");//挑拣状态
        add.setIsSign("0");//签收状态
        add.setIsAck("0");//处置确认
        add.setSource("1");//0-默认 1-推送
//        add.setIsCheck("0");

        if(!LoginHelper.checkLoginUser()){
            add.setCreateBy("admin");
            add.setCreateTime(new Date());
            add.setUpdateBy("admin");
            add.setUpdateTime(new Date());
        }

        if(bo.getItems() != null && bo.getItems().size() > 0){
            for (DealDtlVo item : bo.getItems()){
                DealDtl dtl = BeanUtil.toBean(item, DealDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setDealId(add.getId());
                dtl.setDelFlag("0");
                dtl.setNums(item.getNums() == null ? 1L : item.getNums());

                if(!LoginHelper.checkLoginUser()){
                    dtl.setCreateBy("admin");
                    dtl.setCreateTime(new Date());
                    dtl.setUpdateBy("admin");
                    dtl.setUpdateTime(new Date());
                }
                dealDtlMapper.insert(dtl);
            }
        }
        if(bo.getOss() != null && bo.getOss().size() > 0){
            for(SysOss oss : bo.getOss()){
                oss.setBuss("Deal");
                oss.setObjid(add.getId());
                sysOssMapper.updateById(oss);
            }
        }
        commonService.saveOperatorLog(StringUtils.isNotEmpty(add.getTaskId())?add.getTaskId():add.getId(),"wms","创建处置单");
        return add;
    }

    /**
     * 修改处置
     *
     * @param bo 处置
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Deal updateByBo(DealBo bo) {
        Deal update = BeanUtil.toBean(bo, Deal.class);
        validEntityBeforeSave(update);

        List<DealDtl> dtls = new ArrayList<>();
        List<DealDtl> dels = new ArrayList<>();

        if(bo.getItems() != null && bo.getItems().size() > 0){
            for (DealDtlVo item : bo.getItems()){
                DealDtl dtl = BeanUtil.toBean(item, DealDtl.class);

                LambdaQueryWrapper<DealDtl> lqw = Wrappers.lambdaQuery();
                lqw.eq(StringUtils.isNotBlank(update.getId()), DealDtl::getDealId, update.getId());
                lqw.eq(StringUtils.isNotBlank(item.getPno()), DealDtl::getPno, item.getPno());
                DealDtl dealDtl = dealDtlMapper.selectOne(lqw);

                if(StringUtils.isEmpty(item.getId()) && dealDtl == null){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setDealId(update.getId());
                    dtl.setDelFlag("0");
                }else {
                    dtl.setId(dealDtl.getId());
                }
                dtl.setNums(item.getNums() == null ? 1L : item.getNums());
                if(dtl.getDelFlag().equals("0")){
                    dtls.add(dtl);
                }else{
                    dels.add(dtl);
                }
            }
        }
        if(dtls != null && dtls.size() > 0){
            dealDtlMapper.insertOrUpdateBatch(dtls);
        }
        if(dels != null && dels.size() > 0){
            dealDtlMapper.deleteBatchIds(dels);
        }
        if(bo.getOss() != null && bo.getOss().size() > 0){
            for(SysOss oss : bo.getOss()){
                oss.setBuss("Deal");
                oss.setObjid(update.getId());
                sysOssMapper.updateById(oss);
            }
        }
//        updateOrder(update.getTaskId(),bo.getItems());

        updateTask(update.getTaskId(),bo.getItems());

        if(StringUtils.isNotEmpty(update.getIsCheck()) && update.getIsCheck().equals("0")){
            update.setChecker(LoginHelper.getNickname());
            update.setCheckTime(new Date());

            //处理审核通过后，库存信息
            if(bo.getIsCheck().equals("1")){
                //查询在库库存
                Inventory inventory = inventoryMapper.selectOne(new LambdaQueryWrapper<Inventory>()
                    .eq(Inventory::getPno,update.getDealNo())
                    .eq(Inventory::getStatus,"0"));
                if(inventory != null){
                    if(inventory.getNums() >= update.getNums()){
                        inventory.setDeals(update.getNums());
                        Long surplus = inventory.getNums() - update.getNums();
                        inventory.setNums(surplus);
                        if(surplus == 0l){
                            inventory.setStatus("1");//全部处置，则设为不在库
                        }
                    }else {
                        throw new ServiceException("库存数不足");
                    }
                    inventoryMapper.updateById(inventory);
                }
            }
        }

        baseMapper.updateById(update);
        return update;
    }

    @Override
    public Deal updateByDealBo(DealBo bo) {
        Deal update = BeanUtil.toBean(bo, Deal.class);
        validEntityBeforeSave(update);

        if(!update.getIsCheck().equals("0")){
            update.setChecker(LoginHelper.getNickname());
            update.setCheckTime(new Date());
            update.setOperator(LoginHelper.getUserId());
        }

        if(bo.getItems() != null && bo.getItems().size() > 0){
            for (DealDtlVo dtlVo :bo.getItems()){
                DealDtl dealDtl = BeanUtil.toBean(dtlVo, DealDtl.class);
                dealDtlMapper.updateById(dealDtl);
            }
        }
        if(bo.getStatus().equals("1")){//处置登记
            update.setRegisterTime(new Date());
            update.setRegistrant(LoginHelper.getNickname());
            commonService.dealPush(update.getId());
        }
        if(bo.getOss() != null && bo.getOss().size() > 0){
            for (SysOss oss:bo.getOss()){
                oss.setBuss("deal_register");
                oss.setObjid(update.getId());
                sysOssMapper.updateById(oss);
            }
        }

        baseMapper.updateById(update);
        return update;
    }

    @Override
    public Boolean updateDealByBo(DealBo bo) {
        Deal update = BeanUtil.toBean(bo, Deal.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) >0;
    }

    @Override
    public Boolean validateDeal(DealBo bo) {
        if(bo.getValidateItems() != null && bo.getValidateItems().size() > 0){
            List<Deal> validateItems = bo.getValidateItems().stream().map(item->{
                Deal update = BeanUtil.toBean(item, Deal.class);
                validEntityBeforeSave(update);
                update.setIsAck("1");
                update.setAcker(LoginHelper.getNickname());
                update.setAckTime(new Date());
                return update;
            }).collect(Collectors.toList());
           return baseMapper.updateBatchById(validateItems);
        }
        return false;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Deal entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除处置
     *
     * @param ids 需要删除的处置主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public DealVo getDealByVo(DealBo bo) {
        DealVo deal = baseMapper.selectVoOne(new LambdaQueryWrapper<Deal>()
            .eq(Deal::getDealNo,bo.getDealNo())
            .eq(Deal::getTaskId,bo.getTaskId()));
        return deal;
    }

    public String getNo(){
        LambdaQueryWrapper<Deal> lqw = Wrappers.lambdaQuery();
        Long maxNumObject = baseMapper.selectCount(lqw);
        String num = "";
        String todayStr = DateUtils.date2String(new Date(), "yyMMdd");

        if (maxNumObject == null) {
            num = todayStr + "000001";
        } else {
            String maxnumStr = "00000" + maxNumObject.toString();
            String maxnumNo = maxnumStr.substring(maxnumStr.length() - 6, maxnumStr.length());
            String nextnumNo = StringUtils.nextNo(maxnumNo, 6);
            num = todayStr + nextnumNo;
        }
        return num;
    }

    public void updateOrder(String taskId,List<DealDtlVo> items){
        OrderBo orderBo = new OrderBo();
        orderBo.setTaskId(taskId);
        List<OrderVo> orderVos = orderMapper.selectOrderList(orderBo);
        List<OrderDtl> dtls = new ArrayList<>();
        if(orderVos != null && orderVos.size() > 0){
            OrderVo vo = orderVos.get(0);
            for (DealDtlVo item:items){
                OrderDtl dtl = BeanUtil.toBean(item,OrderDtl.class);

                LambdaQueryWrapper<OrderDtl> lqw = Wrappers.lambdaQuery();
                lqw.eq(StringUtils.isNotBlank(vo.getId()), OrderDtl::getOrderId, vo.getId());
                lqw.eq(StringUtils.isNotBlank(item.getPno()), OrderDtl::getPno, item.getPno());
                OrderDtl orderDtl = orderDtlMapper.selectOne(lqw);

                if(StringUtils.isEmpty(item.getId()) && orderDtl == null){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setOrderId(vo.getId());
                    dtl.setDelFlag("0");
                    dtl.setStatus("0");
                }else {
                    dtl.setId(orderDtl.getId());
                }
                dtls.add(dtl);
            }
        }
        if(dtls != null && dtls.size() > 0){
            orderDtlMapper.insertOrUpdateBatch(dtls);
        }
    }

    public void updateTask(String taskId,List<DealDtlVo> items){
        TaskVo taskVo = taskMapper.selectTaskVoByID(taskId);
        List<TaskDtl> dtls = new ArrayList<>();
        if(taskVo != null){
            for (DealDtlVo item:items){
                TaskDtl dtl = BeanUtil.toBean(item,TaskDtl.class);

                LambdaQueryWrapper<TaskDtl> lqw = Wrappers.lambdaQuery();
                lqw.eq(StringUtils.isNotBlank(taskVo.getId()), TaskDtl::getTaskId, taskVo.getId());
                lqw.eq(StringUtils.isNotBlank(item.getPno()), TaskDtl::getPno, item.getPno());
                TaskDtl taskDtl = taskDtlMapper.selectOne(lqw);

                if(StringUtils.isEmpty(item.getId()) && taskDtl == null){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setTaskId(taskVo.getId());
                    dtl.setDelFlag("0");
                }else {
                    dtl.setId(taskDtl.getId());
                }
                dtls.add(dtl);
            }
        }
        if(dtls != null && dtls.size() > 0){
            taskDtlMapper.insertOrUpdateBatch(dtls);
        }
    }

    //日志添加
    public void  addOperatorLog(String objid,String type,String content){
        OperatorLog log = new OperatorLog();
        log.setId(IdUtil.simpleUUID());
        log.setObjid(objid);
        log.setDelFlag("0");
        log.setLogTime(new Date());
        if(LoginHelper.checkLoginUser()){
            log.setUserId(LoginHelper.getUserId());
            log.setOperator(LoginHelper.getNickname());
        }else{
            log.setOperator("--");
        }

        log.setLogType(type);
        log.setContent(content);
        logMapper.insert(log);
    }
}
